package com.superlz.demo.security.browser;

import com.superlz.demo.security.core.properties.SecurityProperties;
import com.superlz.demo.security.core.validate.code.ValidateCodeFilter;
import com.superlz.demo.security.core.validate.code.ValidateCodeSecurityConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
 * 1.extends WebSecurityConfigurerAdapter
 * 2.添加@Configuration
 *
 * -----
 *
 * 1. 打开security.basic.enabled = true
 * 2. 访问任意接口，例：http://localhost:8060/user
 * 3. 默认账号：user，密码：在控制台查看（Using default security password:）
 *
 */
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private SecurityProperties securityProperties;

    @Autowired
    private AuthenticationSuccessHandler superlzAuthenticationSuccessHandler;

    @Autowired
    private AuthenticationFailureHandler superlzAuthenctiationFailureHandler;

    @Autowired
    private ValidateCodeSecurityConfig validateCodeSecurityConfig;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private UserDetailsService userDetailsService;

    /**
     * 密码加密
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);
        // 自动创建persistent_logins表(注意只能创建一次)
		// tokenRepository.setCreateTableOnStartup(true);
        return tokenRepository;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        // lz:通过Controller中转，跳转到自定义页

        // .表单登录.登录页面.登录请求url.请求的授权.任何请求.都需要身份认证.csrf跨域请求防护
        http.apply(validateCodeSecurityConfig)
                .and()
                .formLogin()
                .loginPage("/authentication/require")
                .loginProcessingUrl("/authentication/form")
                .successHandler(superlzAuthenticationSuccessHandler)
                .failureHandler(superlzAuthenctiationFailureHandler)
                .and()
                .rememberMe().tokenRepository(persistentTokenRepository())
                .tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSeconds() )
                .and()
                .authorizeRequests()
                .antMatchers("/authentication/require",
                        securityProperties.getBrowser().getLoginPage(),
                        "/code/image").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .csrf().disable();

        // .表单登录.自定义登录页面.请求的授权.任何请求.都需要身份认证
        /*http.formLogin()
                .and()
                .authorizeRequests()
                .anyRequest()
                .authenticated();*/

        // 该为SpringSecurity的默认方式
        // .httpBasic登录.请求的授权.任何请求.都需要身份认证
        /*http.httpBasic()
                .and()
                .authorizeRequests()
                .anyRequest()
                .authenticated();*/
    }

}
